package com.example.system.service.impl;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.starter.util.ExceptionUtil;
import com.example.system.convert.DeptConvert;
import com.example.system.dto.DeptDto;
import com.example.system.entity.Dept;
import com.example.system.mapper.DeptMapper;
import com.example.system.service.IDeptService;
import org.springframework.stereotype.Service;

import javax.validation.constraints.NotNull;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 *
 * @author 王令
 * @since 2022-10-23
 */
@Service
public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements IDeptService {

    @Override
    public void create(DeptDto deptDto) {
        Dept dept = DeptConvert.INSTANCE.toDept(deptDto);
        assertUniqueRecord(dept);
        this.save(dept);
    }

    @Override
    public void update(DeptDto deptDto) {
        Dept dept = DeptConvert.INSTANCE.toDept(deptDto);
        if (ObjectUtil.equal(dept.getId(), dept.getParentId())) {
            throw ExceptionUtil.wrap("上级项不能是自己本身");
        }
        assertUniqueRecord(dept);
        this.updateById(dept);
    }

    @Override
    public void deleteById(Long id) {
        assertSafeDelete(id);
        this.removeById(id);
    }

    @Override
    public List<Tree<Long>> listWithTree() {
        List<TreeNode<Long>> treeNodes =
                baseMapper.selectList(Wrappers.<Dept>lambdaQuery().orderByAsc(Dept::getOrder).orderByAsc(Dept::getId))
                        .stream().map(getNodeFunction()).collect(Collectors.toList());
        return TreeUtil.build(treeNodes, 0L);
    }

    @NotNull
    private Function<Dept, TreeNode<Long>> getNodeFunction() {
        return dept -> {
            TreeNode<Long> node = new TreeNode<>();
            node.setId(dept.getId());
            node.setName(dept.getName());
            node.setParentId(dept.getParentId());
            node.setWeight(dept.getOrder());
            Map<String, Object> extra = new HashMap<>();
            extra.put("code", dept.getCode());
            extra.put("order", dept.getOrder());
            extra.put("createTime", dept.getCreateTime());
            extra.put("updateTime", dept.getUpdateTime());
            node.setExtra(extra);
            return node;
        };
    }

    private void assertUniqueRecord(Dept dept) {
        LambdaQueryWrapper<Dept> wrapper = Wrappers.<Dept>lambdaQuery()
                .eq(Dept::getCode, dept.getCode())
                .ne(dept.getId() != null, Dept::getId, dept.getId());
        Dept one = baseMapper.selectOne(wrapper);
        if (one != null) {
            throw ExceptionUtil.wrap("组织机构编码已存在");
        }
    }

    private void assertSafeDelete(Long id) {
        Integer count = baseMapper.selectCount(Wrappers.<Dept>lambdaQuery().eq(Dept::getParentId, id));
        if (count != null && count > 0) {
            throw ExceptionUtil.wrap("存在下级项，不能删除");
        }
    }

}
